package Sync
{
	import Common.Deleter;
	import Service.ServiceManager;
	import entity.EntityManager;
	import flash.utils.*;
	import logic.GameLogic;
	import Sync.SyncSystem;
	
	
	public class Client implements IListener
	{
		private var bufferRead:ByteArray = null;
		private var bufferWrite:ByteArray = null;
		private var receiveBuffer:ByteArray = null;
		private var dataBuffer:ByteArray = null;
		private var useExeBufferNo:int;
		private var exeStream:Stream = null;
		
		
		public function Client()
		{
			bufferRead = new ByteArray;
			bufferWrite = new ByteArray;	
			dataBuffer = new ByteArray;
			exeStream = new Stream;
			bufferRead.endian = Endian.LITTLE_ENDIAN;
			bufferWrite.endian = Endian.LITTLE_ENDIAN;
			dataBuffer.endian = Endian.LITTLE_ENDIAN;
			
		}
		
		public function onServerConnected():void{}
		
		public function onServerClosed():void{}
		
		public function onSocketError():void{}
		
		public function onServerMessage(netPackage:Stream):void
		{
			var msgType:int = netPackage.readInt();
			
			if (msgType == ConstValue.MSG_ID_SYNC)
			{
				if (ConstValue.BROADCAST == netPackage.readInt())
				{
					forceBufferStep();
					bufferWrite.writeBytes(netPackage.getByteArray(), netPackage.getByteArray().position, netPackage.getByteArray().length - netPackage.getByteArray().position);
				}				
			}
			
		}
		
		public function forceBufferStep():void
		{
			while (true)
			{
				step();
				
				if (bufferRead.bytesAvailable == 0)
				{
					return;
				}			
				
			}
			
		}
		
		private function swapBuffer():void
		{
			var buffer:ByteArray = bufferRead;
			bufferRead = bufferWrite;
			bufferWrite = buffer;
		}
		
		public function step():void
		{
			var sync:SyncSystem = SyncSystem.getInstance();
			
			if (bufferRead.bytesAvailable == 0)
			{
				bufferRead.clear();
				
				swapBuffer();
				
				bufferRead.position = 0;
				
				if (bufferRead.bytesAvailable == 0)
				{
					return;
				}
			}
			
			exeStream.setByteArray(bufferRead);
			
			while (true)
			{
				var instFlag:int = bufferRead.readInt();
				if (instFlag == ConstValue.systemStepInstruct)
				{
					break;
				}
				
				var sender:uint = exeStream.readInt();
				var receiver:uint = exeStream.readInt();
				var instruct:uint = exeStream.readInt();
				var dataSize:uint = exeStream.readInt();
				
				dataBuffer.writeBytes(bufferRead, bufferRead.position, dataSize);
				bufferRead.position = bufferRead.position + dataSize;
				dataBuffer.position = 0;
				
				var tmpStream:Stream = new Stream;
				tmpStream.setByteArray(dataBuffer);
				
				trace("client step :" + getTimer());
				
				EntityManager.getInstance().onMessage(sender, receiver, instruct, tmpStream);
				
				dataBuffer.clear();
				
				if(bufferRead.bytesAvailable == 0)
				{
					bufferRead.clear();
				}
			}
			
			GameLogic.getInstance().logicStep(0);
			
		}
		
		public function release():void
		{
			Deleter(bufferRead);
			Deleter(bufferWrite);
		}
	
	}
}